/*
增加模块流程：
1、#include 模块头文件
2、增加主菜单项目。无法录入汉字，可临时录入英文，然后在属性编辑修改文本内容，给模块的action命名。
3、编辑action，图标从资源选择，否则程序运行无法显示图标。
4、h文件slots增加： _triggered()，private增加指向form的指针变量。
5、cpp文件构造增加： form指针置空， connect SIGNAL & SLOT, 实现slot。
6、需要关闭即销毁的窗口，在destroyWind中增加代码。模块本身也需要增加相关signal，并在窗口关闭时发出signal。
7、主窗口关闭前，清理未关闭的窗口。if(sjzdwh != NULL) delete sjzdwh;
8、
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "pub_var.h"
#include "com_dialog_test.h"
#include <QDebug>
#include <QMessageBox>
#include <QFile>
#include <QDesktopWidget>
#include <QCloseEvent>
#include <QIcon>
#include <windows.h>
#include <QDir>
#include <QSharedMemory>
#include <QHostInfo>


#include "tj_dialog_cfdy.h"    //处方打印
#include "sk_dialog_gh.h"      //挂号
#include "com_env_config.h"  //工作环境设置
#include "sk_recipe_manage.h"   //财务，发票管理
#include "tj_formdrugitems.h"  //药品品种定义
#include "tj_form_drugquery.h" //药品查询
#include "sk_form_sk.h"        //收款
#include "sk_form_tf.h"        //退费
#include "com_form_chagepassword.h"//修改口令
#include "sk_form_gzltj.h"     //收款统计查询
#include "tj_form_recipeacount.h"//处方统计
#include "yb_form_jcmlxz.h"    //医保基础目录下载
#include "yb_form_xmdz.h"      //医保项目对照
#include "yb_form_xxcx.h"      //医保信息查询
#include "yb_form_jsdz.h"      //医保结算对账
#include "yb_form_dzbl.h"      //门诊病历上传
#include "yb_form_hj.h"      //医保工作环境配置
#include "tj_form_input.h"     //药品账外数量管理
#include "yb_form_qlsjsc.h"     //全量数据上传
#include "yk_form_rk.h" //药库，入库
#include "ys_form_bzgl.h"   //医生接诊处置
#include "ys_form_env.h"    //医生基础环境
#include "com_form_jbgl.h"  //通用，价表管理
#include "tj_form_ybxmcx.h" //医保项目查询
#include "com_form_user.h" //用户管理
#include "com_dialog_test.h" //功能测试模块
#include "yk_form_kccx.h"   //库存查询
#include "com_form_dept.h"  //科室管理
#include "ys_form_sfgl.h"   //患者随访
#include "com_form_undrug.h"    //非药品维护
#include "tj_form_recipe_check.h"   //付药核对
#include "ys_form_patient_detail.h"  //患者详情查询
//#include "tj_form_barcode_return.h"   //退药条码录入
#include "sk_form_base.h"   //财务基础数据
#include "com_data_dump.h"  //数据导入导出
#include "lab_main.h"   //化验室
#include "yk_form_wzkccx.h"//物资库查询
#include "yk_form_wzrk.h"//物资库入出
#include "yb_log_browse.h"//医保交易日志浏览
#include "tj_drug_consume_dept.h"//默认处方执行药房配置
#include "physio_main.h"    //中医治疗
#include "ys_senior_check.h"    //超职级用药
#include "yk_baseitem.h"    //药库基础信息维护
#include "yk_purchase_plan.h" //药品入库验收

//const int TIMER_LOG = 5000;
//const int MAX_CONNECT_COUNT = 3;
QList<QCameraInfo> cameraList;

const int LOCAL_PORT = 12345;
extern QSharedMemory share;

//QMenuBar * mainmenu;
QStringList menuList;       //菜单列表，角色授权使用

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowIcon(QIcon(":/icons/仁晟.png"));
    qDebug()<<"system start!";
    qDebug() << "Library paths:" << QCoreApplication::libraryPaths();

    qrm = QSqlQuery(pub::db_m);
    qro = QSqlQuery(pub::db_o);

    QList<QAction*> act;
    QList<QAction*> act0;
    act = this->menuBar()->actions();

    //提取完整菜单结构。
    foreach(QAction *a, act)
    {
        menuList <<  a->menu()->title() + "^" +a->menu()->objectName();//"+" +
        act0 = a->menu()->actions();
        foreach(QAction *b, act0)
        {
            if(!b->text().isEmpty())
            {
                menuList << "    " + b->text() + "^" +b->objectName() + "^" + a->menu()->objectName();
            }
        }
    }

    QSize s;

    s.setWidth( QApplication::desktop()->height()/20);
    s.setHeight(QApplication::desktop()->height()/20);
    ui->tbMain->setIconSize(s);

    //提取用户已授权菜单项
    QString sq = "select r.menu_id from com_roles r,com_privileges p where p.type = 'role' "
                 " and r.role_name = p.role_dept and p.code = '" + pub::usr_code + "' ";
    qrm.exec(sq);
    QString ids;

    while(qrm.next())
    {
        ids += qrm.value(0).toString() + "^" ;
    }

    //提取需要显示到工具栏的菜单项
    sq = "select name from com_privileges where type = 'tool_bar' ";
    qrm.exec(sq);
    QString tools;

    while(qrm.next())
    {
        tools += qrm.value(0).toString() + "^" ;
    }

    //待修改为可删可增

    foreach(QAction *a, ui->menubar->actions())
    {
        if( ids.indexOf(a->menu()->objectName() ) < 0 )
        {
            //移除未被授权菜单项
            //ui->menubar->removeAction(a);
            //ui->menubar->hide removeAction(a);
            a->setVisible(false);
        }
        else
        {
            a->setVisible(true);
            ui->tbMain->addSeparator();
            foreach(QAction *b, a->menu()->actions())
            {
                QString item_name = b->objectName();
                if( ids.indexOf(item_name) < 0)
                {
                    //移除未被授权菜单项
                    //a->menu()->removeAction(b);
                    b->setVisible(false);
                }
                else
                {
                    b->setVisible(true);
                    if( tools.indexOf(item_name) > -1)
                    {
                        //添加授权项目到工具栏
                        ui->tbMain->addAction(b);
                    }
                }
            }
        }
    }

    this->setGeometry(0, 0, QApplication::desktop()->width() -50, 10);
    statusBar()->setVisible(false);
    //statusBar()->showMessage("Status is here...", 3000);

    connect(ui->actionreg,SIGNAL(triggered()),this,SLOT(reg_trigged()));
    connect(ui->actionexit,SIGNAL(triggered()),this,SLOT(exit_trigged()));
    connect(ui->action_func_test,SIGNAL(triggered()),this,SLOT(action_func_test_trigged()));
    connect(ui->action_ghsz,SIGNAL(triggered()),this,SLOT(action_ghsz_trigged()));
    connect(ui->action_cfdy,SIGNAL(triggered()),this,SLOT(action_cfdy_trigged()));
    connect(ui->actionDrugItems,SIGNAL(triggered()),this,SLOT(actionDrugItems_trigged()));
    connect(ui->action_recipe_manage,SIGNAL(triggered()),this,SLOT(action_recipe_manage_trigged()));
    connect(ui->actionDocApply,SIGNAL(triggered()),this,SLOT(action_tj_ybxmcx_trigged()));
    connect(ui->action_drugQuery,SIGNAL(triggered()),this,SLOT(action_drugQuery_trigged()));
    connect(ui->action_sk,SIGNAL(triggered()),this,SLOT(action_sk_trigged()));
    connect(ui->action_tf,SIGNAL(triggered()),this,SLOT(action_tf_trigged()));
    connect(ui->actionChangePass,SIGNAL(triggered()),this,SLOT(action_changePass_trigged()));
    connect(ui->actionGzltj,SIGNAL(triggered()),this,SLOT(action_gzltj_trigged()));
    connect(ui->action_cftj,SIGNAL(triggered()),this,SLOT(action_cftj_trigged()));
    connect(ui->action_jcmlxz,SIGNAL(triggered()),this,SLOT(action_jcmlxz_trigged()));
    connect(ui->action_xmdz,SIGNAL(triggered()),this,SLOT(action_xmdz_trigged()));
    connect(ui->action_xxcx,SIGNAL(triggered()),this,SLOT(action_xxcx_trigged()));
    connect(ui->action_jsdz,SIGNAL(triggered()),this,SLOT(action_jsdz_trigged()));
    connect(ui->action_dzbl,SIGNAL(triggered()),this,SLOT(action_dzbl_trigged()));
    connect(ui->action_ybhj,SIGNAL(triggered()),this,SLOT(action_ybhj_trigged()));
    connect(ui->action_InOut,SIGNAL(triggered()),this,SLOT(action_InOut_trigged()));
    connect(ui->action_qlsjsc , &QAction::triggered, this, &MainWindow::action_qlsjsc_trigged);
    connect(ui->action_yk_rk , &QAction::triggered, this, &MainWindow::action_yk_rk_trigged);
    connect(ui->action_ys_bzgl , &QAction::triggered, this, &MainWindow::action_ys_bzgl_trigged);
    connect(ui->action_ys_env , &QAction::triggered, this, &MainWindow::action_ys_env_trigged);
    connect(ui->action_com_jbgl , &QAction::triggered, this, &MainWindow::action_com_jbgl_trigged);
    connect(ui->action_tj_ybxmcx , &QAction::triggered, this, &MainWindow::action_tj_ybxmcx_trigged);
    connect(ui->action_user , &QAction::triggered, this, &MainWindow::action_user_trigged);
    connect(ui->action_kccx, &QAction::triggered, this,  &MainWindow::action_kccx_trigged);
    connect(ui->action_dept , &QAction::triggered, this, &MainWindow::action_dept_trigged);
    connect(ui->action_ys_sfgl , &QAction::triggered, this, &MainWindow::action_ys_sfgl_trigged);
    connect(ui->action_undrug , &QAction::triggered, this, &MainWindow::action_undrug_trigged);
    connect(ui->action_recipe_check , &QAction::triggered, this, &MainWindow::action_recipe_check_trigged);
    connect(ui->action_patient_detail , &QAction::triggered, this, &MainWindow::action_patient_detail_trigged);
    connect(ui->action_fin_base , &QAction::triggered, this, &MainWindow::action_fin_base_trigged);
    connect(ui->action_data_dump , &QAction::triggered, this, &MainWindow::action_data_dump_trigged);
    connect(ui->action_lab_main , &QAction::triggered, this, &MainWindow::action_lab_main_trigged);
    connect(ui->action_re_login , &QAction::triggered, this, &MainWindow::action_re_login_trigged);
    connect(ui->action_mat_query , &QAction::triggered, this, &MainWindow::action_mat_query_trigged);
    connect(ui->action_mat_io , &QAction::triggered, this, &MainWindow::action_mat_io_trigged);
    connect(ui->action_log_browse , &QAction::triggered,this, &MainWindow::action_log_browse_trigged);
    connect(ui->action_tj_drug_consume_dept, &QAction::triggered,this, &MainWindow::action_tj_drug_consume_dept_trigged);
    connect(ui->action_physio, &QAction::triggered, this, &MainWindow::action_physio_trigged);
    connect(ui->action_patient_pic, &QAction::triggered, this, &MainWindow::action_tj_drug_consume_dept_trigged);
    connect(ui->action_senior_reci_ck, &QAction::triggered, this, &MainWindow::action_senior_reci_ck_trigged);
    connect(ui->action_yk_baseitem, &QAction::triggered, this, &MainWindow::action_yk_baseitem_trigged);
    connect(ui->action_purchase_plan, &QAction::triggered, this, &MainWindow::action_purchase_plan_trigged);

    //变更身份
    com_re_signin = new Com_re_signin();
    connect( com_re_signin, &Com_re_signin::re_signin, this, &MainWindow::re_signin);

    tm = new QTimer;
    tm2 = new QTimer;


    connect(tm, SIGNAL(timeout()), this, SLOT(updateTitle()));
    connect(tm2, SIGNAL(timeout()), this, SLOT(waitInitFinish()));

    QSettings setIni("clin.ini", QSettings::IniFormat);

    pub::local_version = QString(__DATE__) + " " + QString(__TIME__);

    QString title = "门诊简易系统 - Built at " + pub::local_version + " - " ;
    title += pub::hos_name;
    //title += " - Version  " + pub::local_version + "  D.P. Sun";
    title += " - " + pub::usr_name;
    title += " - " + pub::dp_name;

    if(pub::DEBUG)
    {
        title += " （当前登录为测试模式）";
    }

    this->setWindowTitle( title );


    //文件下载之后的存储路径
    pub::downloadPath = setIni.value("system/downloadPath").toString();

    if(pub::downloadPath.isEmpty()){
        //下载路径未设置，设置为默认值
        pub::downloadPath = "/0down";
        setIni.setValue("system/downloadPath", "/0down");

    }

    QDir d(pub::downloadPath);

    pub::downloadPath = d.path(); //过滤配置文件可能出现的错误字符

    if( ! d.exists() ){
        //路径不存在，按指定的名字建立新路径

        if(!d.mkdir(pub::downloadPath)){
            QMessageBox::warning(this, "注意", "指定文件存储路径无效！默认路径为本级盘符:\\0down\\");
            pub::downloadPath = "/0down";
            setIni.setValue("system/downloadPath", pub::downloadPath);
            d.setPath(pub::downloadPath);
            if(!d.exists() && !d.mkdir(pub::downloadPath)){
                QMessageBox::warning(this, "注意", "建立默认路径失败!");
            }
        }
    }



    //本机读卡器型号
    pub::local_carddriver = setIni.value("insurance/carddriver").toString();  //本机读卡器型号

    //获取本机工作IP
    QString iptmp = setIni.value("sys/ip").toString();
    QStringList ips;
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list){
        if(address.protocol() == QAbstractSocket::IPv4Protocol){ //IPv4地址
            ips <<address.toString();
        }
    }
    foreach(QString ip, ips){
        if(ip.indexOf(iptmp) >=0){
            pub::localIP = ip;
            break;
        }
    }

    if(pub::localIP.isEmpty()){//无匹配，选第一项作为默认
        pub::localIP = ips[0];
    }

    qro.exec("update com_loginlog set log_address = '" + pub::localIP + "' "
             " where log_index = '" + pub::LOGINSESSION + "'");

    //本机Mac
    // 如果此网络接口被激活并且正在运行并且不是回环地址，则就是我们需要找的Mac地址
    QList<QNetworkInterface> nets = QNetworkInterface::allInterfaces();// 获取所有网络接口列表
    int nCnt = nets.count();

    for(int i = 0; i < nCnt; i ++){
        if(nets[i].flags().testFlag(QNetworkInterface::IsUp)
                && nets[i].flags().testFlag(QNetworkInterface::IsRunning)
                && !nets[i].flags().testFlag(QNetworkInterface::IsLoopBack))
        {
            pub::localMac = nets[i].hardwareAddress();
            break;
        }
    }

    //初始化医保动态库环境
    qDebug()<<"initialYb";
    ybBusiness = new ThreadYb(this);
    ybBusiness->moveToThread(&thread);
    qDebug()<<"start";
    thread.start();
    QMetaObject::Connection connRet =
    connect(this, SIGNAL(opThread(int, QString)), ybBusiness, SLOT(doWork(int, QString)));
    Q_ASSERT(connRet);
    QFile f;
    QString i = setIni.value("insurance/insurance").toString();
    if(f.exists("HeaSecReadInfo.dll") && i == "1"){    //库文件存在且允许使用
        lib.setFileName("HeaSecReadInfo");
        if(lib.load()){
            //pub::BUSINESS = (pub::pBUSINESS)lib.resolve("BUSINESS_HANDLE");
            pub::Init = (pub::pInit)lib.resolve("Init");
            pub::DailySinIn = (pub::pDailySinIn)lib.resolve("DailySinIn");
            pub::EcQuery = (pub::pEcQuery)lib.resolve("EcQuery");
            pub::ReadSFZ = (pub::pReadSFZ)lib.resolve("ReadSFZ");
            pub::ReadCardBas = (pub::pReadCardBas)lib.resolve("ReadCardBas");
            pub::ChangePIN = (pub::pChangePIN)lib.resolve("ChangePIN");

            QMetaObject::Connection connRet =
            connect(ybBusiness, SIGNAL(resultReady(int, QString, QString)),
                    this, SLOT(handleInitial(int, QString, QString)));
            Q_ASSERT(connRet);
            //statusBar()->setVisible(true);
            this->setWindowTitle("医保环境初始化 ");
qDebug()<<"timer will start.";
            tm->start(500);

            QJsonObject in;

            QString lgpt = pub::base_path;
            lgpt.append("/dll_logs/");

            in.insert("IP", pub::hos_ybjy_ip);//	服务端IP地址
            in.insert("PORT", pub::hos_ybjy_port);//	服务端端口
            in.insert("TIMEOUT", "15");//	超时
            in.insert("LOG_PATH", lgpt);//	动态库日志目录
            in.insert("EC_URL", pub::hos_dzpz);//	电子凭证中台URL
            in.insert("DRIVER", pub::local_carddriver);//	读卡机具厂家类型
            in.insert("API_NAME", "");//	CSB的_api_name
            in.insert("API_VERSION", "");//	CSB的_api_version
            in.insert("ACCESS_KEY", "");//	CSB的_api_access_key
            in.insert("SECRETKEY", "");//	CSB的secretKey
            in.insert("ORG_ID", pub::hos_ybbh);//	定点编号
            in.insert("AREA_CODE", pub::hos_insuplc);//	定点所属行政区划代码
            in.insert("EXT", "");//	JSON对象字符串

            QJsonDocument indoc ;
            indoc.setObject(in);

            qDebug()<<"Initial"<<indoc;


            QString sq = "insert into com_business (tmstmp,ywbh,user,jysj,jyfs,v_in,v_out) values "
                 "(now(),'dllInit','" + pub::usr_code
                    + "',DATE_FORMAT(now(),'%Y-%m-%d %T'),'init','"+ indoc.toJson(QJsonDocument::Compact) +"','')";
            if(!qrm.exec(sq)){
                QMessageBox::information(this,"注意","保存医保动态库交易日志失败！ ");
                qDebug()<<"initial in :" + sq;
            }

            QString inp = indoc.toJson();
            initFinished = false;
            tm2->start(500);    //查询初始化是否完成
            emit opThread(0, inp);
        }else{
            qDebug()<<("load HeaSecReadInfo failed.");
        }

    }else{
        qDebug()<<" HeaSecReadInfo not exist or not allowed.";
    }

    naManager = new QNetworkAccessManager(this); // new QNetworkAccessManager(this);

    connRet = QObject::connect(naManager, SIGNAL(finished(QNetworkReply*)),
                             this, SLOT(postRequestFinished(QNetworkReply*)));

    Q_ASSERT(connRet);

    request.setUrl(QUrl(pub::hos_ybjy));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    QString time_mode = setIni.value("system/time").toString();

    update_local_datetime(time_mode);

    //检查升级管理程序是否需要升级
    QString fileName = "update.exe";
    qrm.exec("select md5, ver, bin_size from com_update_names where filename = '" + fileName + "'");
    QString md5_remote  ;
    int ver_remote, ver_local, bin_size;
    QString filecontent, md5_combine;
    if(qrm.next())
    {
        md5_remote = qrm.value(0).toString();
        ver_remote = qrm.value(1).toInt();
        bin_size = qrm.value(2).toInt();

        ver_local = setIni.value("version/"+fileName, 0).toInt();

        if(ver_local < ver_remote)      //本地版本小于远程版本
        {
               qDebug()<<" update.exe need to update";
            qrm.exec("select content from com_update_content where filename = '" + fileName + "' order by idx");
            filecontent = "";
            while (qrm.next())
            {
                filecontent += qrm.value(0).toString();
            }

            QByteArray bt = QByteArray::fromBase64(filecontent.toLocal8Bit());

            //计算文件md5
            QByteArray bt_md5_bin = QCryptographicHash::hash(bt , QCryptographicHash::Md5);

            md5_combine = bt_md5_bin.toHex().constData();

            if(md5_combine != md5_remote) //组合后的md5与文件原有md5不一致
            {
                qDebug()<<"下载文件 " + fileName + " 未通过完整性校验！" ;
                return ;
            }

            if(QFile::exists(fileName + ".bk"))
            {
                //存在旧文件备份
                if(!QFile::remove(fileName + ".bk"))   //移除
                {
                    qDebug()<<"移除文件 " + fileName + ".bk" + " 发生错误 ！";
                    return ;
                }
            }
            if(QFile::exists(fileName))
            {
                //当前下载的文件名存在
                if(!QFile::rename(fileName, fileName + ".bk"))   //改名为备份文件
                {
                    qDebug()<<"生成备份文件 " + fileName + ".bk" + " 发生错误 ！";
                    return ;
                }
            }

            QFile f(fileName);
            if (!f.open(QIODevice::WriteOnly))
            {
                qDebug()<<"无法创建文件 " + fileName + " ！";
                QFile::copy(fileName  + ".bk" , fileName);
                return ;
            }
            qint64 bytesWritten = f.write(bt);
            if (bytesWritten != bin_size)
            {
                qDebug()<<"文件 " + fileName + " 写入错误！";
                f.close();
                QFile::remove(fileName);
                QFile::copy(fileName  + ".bk" , fileName);
                return ;
            }
            f.close();

            setIni.setValue("version/"+fileName, ver_remote);
            qDebug()<<" update.exe update to vertion " + QString::number(ver_remote);
        }
        else
        {
            qDebug()<<"no need to update update.exe.";
        }
    }
    else
    {
        qDebug()<<"cann't found update.exe in server.";
    }

    //tcp_socket = new QTcpSocket(this);
    tcp_server = new QTcpServer(this);

    if (!tcp_server->listen(QHostAddress::Any, LOCAL_PORT))
    {
        qDebug()<<"Start Listening failed."<<"\n";
    }
    else
    {
        qDebug()<<"Start Listening ."<<"\n";
        connect(tcp_server, &QTcpServer::newConnection,
                this, &MainWindow::accept_connection);
    }

    tm_receive = new QTimer(this);
    tm_receive->setSingleShot(true);

    connect(tm_receive, &QTimer::timeout,
            this, &MainWindow::tcp_connect_timeout);
}

void MainWindow::action_senior_reci_ck_trigged()
{
    //超职级处方审批
    if( forms["senior_check"] == NULL){  //首次加载
        forms["senior_check"] = new Ys_senior_check();
    }
    forms["senior_check"]->showNormal();
    forms["senior_check"]->activateWindow();

    Ys_senior_check * f = qobject_cast<Ys_senior_check*>(forms["senior_check"]);
    connect(f, &Ys_senior_check::destroyW, [=]{
        delete f;
        forms["senior_check"] = NULL;
    }
    );

}

void MainWindow::action_yk_baseitem_trigged()
{
    //药库基础项目维护
    if( forms["yk_baseitem"] == NULL){  //首次加载
        forms["yk_baseitem"] = new Yk_baseitem();
    }
    forms["yk_baseitem"]->showNormal();
    forms["yk_baseitem"]->activateWindow();

    Yk_baseitem * f = qobject_cast<Yk_baseitem*>(forms["yk_baseitem"]);
    connect(f, &Yk_baseitem::destroyW, [=]{
        delete f;
        forms["yk_baseitem"] = NULL;
    }
    );

}

void MainWindow::action_purchase_plan_trigged()
{
    //药品入库验收
    if( forms["yk_purchase_plan"] == NULL){  //首次加载
        forms["yk_purchase_plan"] = new Yk_purchase_plan();
    }
    forms["yk_purchase_plan"]->showNormal();
    forms["yk_purchase_plan"]->activateWindow();

    Yk_purchase_plan * f = qobject_cast<Yk_purchase_plan*>(forms["yk_purchase_plan"]);
    connect(f, &Yk_purchase_plan::destroyW, [=]{
        delete f;
        forms["yk_purchase_plan"] = NULL;
    }
    );

}

void MainWindow::action_physio_trigged()
{
    //中医治疗
    if( forms["physio_main"] == NULL){  //首次加载
        forms["physio_main"] = new Physio_main();
    }
    forms["physio_main"]->showNormal();
    forms["physio_main"]->activateWindow();

    Physio_main * f = qobject_cast<Physio_main*>(forms["physio_main"]);
    connect(f, &Physio_main::destroyW, [=]{
        delete f;
        forms["physio_main"] = NULL;
    }
    );
}


void MainWindow::action_tj_drug_consume_dept_trigged()
{
    //杂项设置
    if( forms["tj_drug_consume_dept"] == NULL){  //首次加载
        forms["tj_drug_consume_dept"] = new Tj_drug_consume_dept();
    }
    forms["tj_drug_consume_dept"]->showNormal();
    forms["tj_drug_consume_dept"]->activateWindow();

    Tj_drug_consume_dept * f = qobject_cast<Tj_drug_consume_dept*>(forms["tj_drug_consume_dept"]);
    connect(f, &Tj_drug_consume_dept::destroyW, [=]{
        delete f;
        forms["tj_drug_consume_dept"] = NULL;
    }
    );
}

void MainWindow::action_mat_io_trigged()
{
    //物资库，入、出库

    if( forms["yk_wzrk"] == NULL){  //首次加载
        forms["yk_wzrk"] = new Form_yk_wzrk();
    }
    forms["yk_wzrk"]->showNormal();
    forms["yk_wzrk"]->activateWindow();

    Form_yk_wzrk * f = qobject_cast<Form_yk_wzrk*>(forms["yk_wzrk"]);
    connect(f, &Form_yk_wzrk::destroyW, [=]{
        delete f;
        forms["yk_wzrk"] = NULL;
    }
    );
}

void MainWindow::action_log_browse_trigged()
{
    //物资库，入、出库

    if( forms["action_log_browse"] == NULL)
    {
        //首次加载
        forms["action_log_browse"] = new Yb_log_browse();
    }

    forms["action_log_browse"]->showNormal();
    forms["action_log_browse"]->activateWindow();

    Yb_log_browse * f = qobject_cast<Yb_log_browse*>(forms["action_log_browse"]);

    connect(f, &Yb_log_browse::destroyW, [=]{
        delete f;
        forms["action_log_browse"] = NULL;
    }
    );
}

void MainWindow::action_mat_query_trigged()
{
    //物资库信息查询

    if(forms["yk_wzkccx"] == NULL){  //首次加载
        forms["yk_wzkccx"] = new Form_wzkccx();
    }
    forms["yk_wzkccx"]->showNormal();
    forms["yk_wzkccx"]->activateWindow();

    Form_wzkccx * f = qobject_cast<Form_wzkccx*>(forms["yk_wzkccx"]);
    connect(f, &Form_wzkccx::destroyW, [=]{
        delete f;
        forms["yk_wzkccx"] = NULL;
    }
    );

}

void MainWindow::action_re_login_trigged()
{

    com_re_signin->exec();

}

void MainWindow::action_lab_main_trigged()
{
    //化验室

    if(forms["lab_main_win"] == NULL){  //首次加载
        forms["lab_main_win"] = new Lab_main();
    }
    forms["lab_main_win"]->showNormal();
    forms["lab_main_win"]->activateWindow();

    Lab_main * f = qobject_cast<Lab_main*>(forms["lab_main_win"]);
    connect(f, &Lab_main::destroyW, [=]{
        delete f;
        forms["lab_main_win"] = NULL;
    }
    );

}

void MainWindow::action_data_dump_trigged()
{
    //数据转储

    if(forms["data_dump"] == NULL){  //首次加载
        forms["data_dump"] = new com_data_dump();
    }
    forms["data_dump"]->showNormal();
    forms["data_dump"]->activateWindow();

    com_data_dump * f = qobject_cast<com_data_dump*>(forms["data_dump"]);
    connect(f, &com_data_dump::destroyW, [=]{
        delete f;
        forms["data_dump"] = NULL;
    }
    );
}

void MainWindow::action_fin_base_trigged()
{
    //财务基础数据维护

    if(forms["fin_base"] == NULL){  //首次加载
        forms["fin_base"] = new sk_form_base();
    }
    forms["fin_base"]->showNormal();
    forms["fin_base"]->activateWindow();

    sk_form_base * f = qobject_cast<sk_form_base*>(forms["fin_base"]);
    connect(f, &sk_form_base::destroyW, [=]{
        delete f;
        forms["fin_base"] = NULL;
    }
    );

}

void MainWindow::action_recipe_manage_trigged()
{
    //财务发票管理

    if(forms["recipe_manage"] == NULL){  //首次加载
        forms["recipe_manage"] = new RecipeManage();
    }
    forms["recipe_manage"]->showNormal();
    forms["recipe_manage"]->activateWindow();

    RecipeManage * f = qobject_cast<RecipeManage*>(forms["recipe_manage"]);
    connect(f, &RecipeManage::destroyW, [=]{
        delete f;
        forms["recipe_manage"] = NULL;
    }
    );

}

void MainWindow::action_patient_detail_trigged()
{
    //患者信息查询

    if(forms["form_patient_detail"] == NULL){  //首次加载
        forms["form_patient_detail"] = new ys_form_patient_detail();
    }
    forms["form_patient_detail"]->showNormal();
    forms["form_patient_detail"]->activateWindow();

    ys_form_patient_detail * f = qobject_cast<ys_form_patient_detail*>(forms["form_patient_detail"]);
    connect(f, &ys_form_patient_detail::destroyW, [=]{
        delete f;
        forms["form_patient_detail"] = NULL;
    }
    );

}

void MainWindow::action_recipe_check_trigged()
{
    //药局窗口处方核验

    if(forms["form_recipe_check"] == NULL){  //首次加载
        forms["form_recipe_check"] = new tj_form_recipe_check();
    }
    forms["form_recipe_check"]->showNormal();
    forms["form_recipe_check"]->activateWindow();

    tj_form_recipe_check * f = qobject_cast<tj_form_recipe_check*>(forms["form_recipe_check"]);
    connect(f, &tj_form_recipe_check::destroyW, [=]{
        delete f;
        forms["form_recipe_check"] = NULL;
    }
    );

}

void MainWindow::action_undrug_trigged()
{
    //非药品项目管理

    if(forms["undrug"] == NULL){  //首次加载
        forms["undrug"] = new Form_undrug();
    }
    forms["undrug"]->showNormal();
    forms["undrug"]->activateWindow();

    Form_undrug * f = qobject_cast<Form_undrug*>(forms["undrug"]);
    connect(f, &Form_undrug::destroyW, [=]{
        delete f;
        forms["undrug"] = NULL;
    }
    );

}

void MainWindow::action_dept_trigged()
{
    //诊室管理

    if(forms["dept_manage"] == NULL){  //首次加载
        forms["dept_manage"] = new Form_dept();
    }
    forms["dept_manage"]->showNormal();
    forms["dept_manage"]->activateWindow();

    Form_dept * f = qobject_cast<Form_dept*>(forms["dept_manage"]);
    connect(f, &Form_dept::destroyW, [=]{
        delete f;
        forms["dept_manage"] = NULL;
    }
    );

}

void MainWindow::action_ys_sfgl_trigged()
{
    //患者随访管理

    if(forms["ys_sfgl"] == NULL){  //首次加载
        forms["ys_sfgl"] = new Form_ys_sfgl();
    }
    forms["ys_sfgl"]->showNormal();
    forms["ys_sfgl"]->activateWindow();

    Form_ys_sfgl * f = qobject_cast<Form_ys_sfgl*>(forms["ys_sfgl"]);
    connect(f, &Form_ys_sfgl::destroyW, [=]{
        delete f;
        forms["ys_sfgl"] = NULL;
    }
    );

}

void MainWindow::action_kccx_trigged()
{
    //药库 库存查询

    if(forms["yk_kccx"] == NULL){  //首次加载
        forms["yk_kccx"] = new Form_kccx();
    }
    forms["yk_kccx"]->showNormal();
    forms["yk_kccx"]->activateWindow();

    Form_kccx * f = qobject_cast<Form_kccx*>(forms["yk_kccx"]);
    connect(f, &Form_kccx::destroyW, [=]{
        delete f;
        forms["yk_kccx"] = NULL;
    }
    );

}

void MainWindow::action_user_trigged()
{
    //用户管理

    if(forms["com_user"] == NULL){  //首次加载
        forms["com_user"] = new com_Form_user();
    }
    forms["com_user"]->showNormal();
    forms["com_user"]->activateWindow();

    com_Form_user * f = qobject_cast<com_Form_user*>(forms["com_user"]);
    connect(f, &com_Form_user::destroyW, [=]{
        delete f;
        forms["com_user"] = NULL;
    }
    );

}

void MainWindow::action_tj_ybxmcx_trigged()
{
    //医保收费项目查询

    if(forms["tj_ybxmcx"] == NULL){  //首次加载
        forms["tj_ybxmcx"] = new tj_form_ybxmcx();
    }
    forms["tj_ybxmcx"]->showNormal();
    forms["tj_ybxmcx"]->activateWindow();

    tj_form_ybxmcx * f = qobject_cast<tj_form_ybxmcx*>(forms["tj_ybxmcx"]);
    connect(f, &tj_form_ybxmcx::destroyW, [=]{
        delete f;
        forms["tj_ybxmcx"] = NULL;
    }
    );

}

void MainWindow::action_com_jbgl_trigged()
{
    //价表管理，药品、非药品调价

    if(forms["com_jbgl"] == NULL){  //首次加载
        forms["com_jbgl"] = new Form_com_jbgl();
    }
    forms["com_jbgl"]->showNormal();
    forms["com_jbgl"]->activateWindow();

    Form_com_jbgl * f = qobject_cast<Form_com_jbgl*>(forms["com_jbgl"]);
    connect(f, &Form_com_jbgl::destroyW, [=]{
        delete f;
        forms["com_jbgl"] = NULL;
    }
    );

}

void MainWindow::waitInitFinish()
{
    if(initFinished){
        tm2->stop();
        ybSign();   //新医保登录
        ybSigned = true;
        pub::useInsurance = true;  //医保可用
        tm->stop();


    }

    //pub::useInsurance = true;  //医保可用

}
void MainWindow::updateTitle()
{
    //qDebug()<<"updateTitle";
    QString t = this->windowTitle();
    t = t +" .";
    this->setWindowTitle(t);

}

void MainWindow::handleInitial(const int r, const QString o1, const QString o2  )
{
    qDebug()<<"\nhandleInitial start...\n";

    disconnect(ybBusiness, SIGNAL(resultReady(int, QString, QString)),
               this, SLOT(handleInitial(int, QString, QString)));

    qDebug()<<"disconnedted";

    if(r != 0){
        //动态库初始化失败

        qDebug()<<"initial error";

        QMessageBox::information(NULL, "error", "动态库初始化失败：" + o1);
        qDebug()<<"HeaSecReadInfo initial error"<<o1;
        tm->stop(); //停止显示。
        QString sq = "insert into com_business (tmstmp,ywbh,user,jysj,jyfs,v_in,v_out) values "
             "(now(),'dllInit','" + pub::usr_code + "',DATE_FORMAT(now(),'%Y-%m-%d %T'),'init','','"
                + o1 + "^" + o2 + "')"; //.toUtf8()
        if(!qrm.exec(sq)){
            QMessageBox::information(this,"注意","保存医保动态库交易日志失败！ ");
            qDebug()<<"initial out : " + sq;
        }
    }else{

        qDebug()<<"initial success";

        initFinished = true;    //设置动态库初始化成功标志，以启动医保日签到
    }

    //initFinished = true;    //设置动态库初始化成功标志，以启动医保日签到

    //tm->stop();

    //statusBar()->setVisible(false);

    QString title = "门诊简易系统 - Built at " + pub::local_version + " - " ;
    title += pub::hos_name;
    //title += " - Version  " + pub::local_version + "  D.P. Sun";
    title += " - " + pub::usr_name;
    title += " - " + pub::dp_name;

    if(pub::DEBUG)
    {
        title += " （当前登录为测试模式）";
    }

    this->setWindowTitle(title);

    qDebug()<<"\nhandleInitial end.\n";

}


MainWindow::~MainWindow()
{
    delete ui;

    thread.quit();
    thread.wait();

    pub::db_m.close();
    pub::db_o.close();
}

void MainWindow::reg_trigged()
{
    //挂号

    if(forms["dlg_gh"] == NULL){  //首次加载
        forms["dlg_gh"] = new Dialog_gh();
    }
    forms["dlg_gh"]->showNormal();
    forms["dlg_gh"]->activateWindow();

    Dialog_gh * f = qobject_cast<Dialog_gh*>(forms["dlg_gh"]);
    connect(f, &Dialog_gh::destroyW, [=]{
        delete f;
        forms["dlg_gh"] = NULL;
    }
    );
}

void MainWindow::exit_trigged()
{
    this->close();
}



void MainWindow::action_ys_env_trigged()
{
    //医生基础环境设置

    if(forms["ys_env"] == NULL){  //首次加载
        forms["ys_env"] = new Form_ys_env();
    }
    forms["ys_env"]->showNormal();
    forms["ys_env"]->activateWindow();

    Form_ys_env * f = qobject_cast<Form_ys_env*>(forms["ys_env"]);
    connect(f, &Form_ys_env::destroyW, [=]{
        delete f;
        forms["ys_env"] = NULL;
    }
    );

}

void MainWindow::action_func_test_trigged()
{
    //测试模块

    if(forms["dlg_test"] == NULL){  //首次加载
        forms["dlg_test"] = new Dialog_datatrans();
    }
    forms["dlg_test"]->showNormal();
    forms["dlg_test"]->activateWindow();

//    Dialog_datatrans * f = qobject_cast<Dialog_datatrans*>(forms["dlg_test"]);
//    connect(f, &Dialog_datatrans::destroyW, [=]{
//        delete f;
//        forms["dlg_test"] = NULL;
//    }
//    );

}

void MainWindow::action_ghsz_trigged()
{
    //挂号环境配置

    if(forms["dlg_gh_env"] == NULL){  //首次加载
        forms["dlg_gh_env"] = new Dialog_gh_env();
    }
    forms["dlg_gh_env"]->showNormal();
    forms["dlg_gh_env"]->activateWindow();

    Dialog_gh_env * f = qobject_cast<Dialog_gh_env*>(forms["dlg_gh_env"]);
    connect(f, &Dialog_gh_env::destroyW, [=]{
        delete f;
        forms["dlg_gh_env"] = NULL;
    }
    );

}

void MainWindow::action_cfdy_trigged()
{
    //调剂室 处方打印，病志打印，退药等

    int var = abs(pub::check_system_time());

    if( var > 300)
    {
        QMessageBox::warning(NULL, "注意", "本机时间与服务器时间相差过大，请调整时间之后再运行！");
        return;
    }

    if(forms["dlg_cfdy"] == NULL){  //首次加载
        forms["dlg_cfdy"] = new Dialog_cfdy();
    }
    forms["dlg_cfdy"]->showNormal();
    forms["dlg_cfdy"]->activateWindow();

    Dialog_cfdy * f = qobject_cast<Dialog_cfdy*>(forms["dlg_cfdy"]);
    connect(f, &Dialog_cfdy::destroyW, [=]{
        delete f;
        forms["dlg_cfdy"] = NULL;
    }
    );

}

void MainWindow::actionDrugItems_trigged()
{
    //在用药品品种管理

    if(forms["formDrugItems"] == NULL){  //首次加载
        forms["formDrugItems"] = new FormDrugItems();
    }
    forms["formDrugItems"]->showNormal();
    forms["formDrugItems"]->activateWindow();

    FormDrugItems * f = qobject_cast<FormDrugItems*>(forms["formDrugItems"]);
    connect(f, &FormDrugItems::destroyW, [=]{
        delete f;
        forms["formDrugItems"] = NULL;
    }
    );

}

void MainWindow::action_drugQuery_trigged()
{
    //调剂室日常药品查询

    if(forms["formDrugQuery"] == NULL){  //首次加载
        forms["formDrugQuery"] = new FormDrugQuery();
    }
    forms["formDrugQuery"]->showNormal();
    forms["formDrugQuery"]->activateWindow();

    FormDrugQuery * f = qobject_cast<FormDrugQuery*>(forms["formDrugQuery"]);
    connect(f, &FormDrugQuery::destroyW, [=]{
        delete f;
        forms["formDrugQuery"] = NULL;
    }
    );

}

void MainWindow::action_sk_trigged()
{
    //收款

    if(abs(pub::check_system_time()) > 300)
    {
        QMessageBox::warning(NULL, "注意", "本机时间与服务器时间相差过大，请调整时间之后再运行！");
        return;
    }

    if(forms["form_sk"] == NULL){  //首次加载
        forms["form_sk"] = new Form_sk();
    }
    forms["form_sk"]->showNormal();
    forms["form_sk"]->activateWindow();

    Form_sk * f = qobject_cast<Form_sk*>(forms["form_sk"]);
    connect(f, &Form_sk::destroyW, [=]{
        delete f;
        forms["form_sk"] = NULL;
    }
    );


}

void MainWindow::action_tf_trigged()
{
    //退费

    if(forms["form_tf"] == NULL){  //首次加载
        forms["form_tf"] = new Form_tf();
    }
    forms["form_tf"]->showNormal();
    forms["form_tf"]->activateWindow();

    Form_tf * f = qobject_cast<Form_tf*>(forms["form_tf"]);
    connect(f, &Form_tf::destroyW, [=]{
        delete f;
        forms["form_tf"] = NULL;
    }
    );

}

void MainWindow::action_changePass_trigged()
{
    //修改口令

    if(forms["changePassword"] == NULL){  //首次加载
        forms["changePassword"] = new Form_chagePassword();
    }
    forms["changePassword"]->showNormal();
    forms["changePassword"]->activateWindow();

    Form_chagePassword * f = qobject_cast<Form_chagePassword*>(forms["changePassword"]);
    connect(f, &Form_chagePassword::destroyW, [=]{
        delete f;
        forms["changePassword"] = NULL;
    }
    );

}

void MainWindow::action_gzltj_trigged()
{
    //收费工作量统计

    if(forms["gzltj"] == NULL){  //首次加载
        forms["gzltj"] = new Form_gzltj();
    }
    forms["gzltj"]->showNormal();
    forms["gzltj"]->activateWindow();

    Form_gzltj * f = qobject_cast<Form_gzltj*>(forms["gzltj"]);
    connect(f, &Form_gzltj::destroyW, [=]{
        delete f;
        forms["gzltj"] = NULL;
    }
    );

}

void MainWindow::action_cftj_trigged()
{
    //处方统计

    if(forms["cftj"] == NULL){  //首次加载
        forms["cftj"] = new Form_recipeAcount();
    }
    forms["cftj"]->showNormal();
    forms["cftj"]->activateWindow();

    Form_recipeAcount * f = qobject_cast<Form_recipeAcount*>(forms["cftj"]);
    connect(f, &Form_recipeAcount::destroyW, [=]{
        delete f;
        forms["cftj"] = NULL;
    }
    );

}

void MainWindow::action_jcmlxz_trigged()
{
    //基础目录下载

    if(forms["jcmlxz"] == NULL){  //首次加载
        forms["jcmlxz"] = new Form_yb_jcmlxz();
    }
    forms["jcmlxz"]->showNormal();
    forms["jcmlxz"]->activateWindow();

    Form_yb_jcmlxz * f = qobject_cast<Form_yb_jcmlxz*>(forms["jcmlxz"]);
    connect(f, &Form_yb_jcmlxz::destroyW, [=]{
        delete f;
        forms["jcmlxz"] = NULL;
    }
    );

}

void MainWindow::action_xmdz_trigged()
{
    //项目对照

    if(forms["xmdz"] == NULL){  //首次加载
        forms["xmdz"] = new Form_xmdz();
    }
    forms["xmdz"]->showNormal();
    forms["xmdz"]->activateWindow();

    Form_xmdz * f = qobject_cast<Form_xmdz*>(forms["xmdz"]);
    connect(f, &Form_xmdz::destroyW, [=]{
        delete f;
        forms["xmdz"] = NULL;
    }
    );

}

void MainWindow::action_xxcx_trigged()
{
    //信息查询

    if(forms["xxcx"] == NULL){  //首次加载
        forms["xxcx"] = new Form_xxcx();
    }
    forms["xxcx"]->showNormal();
    forms["xxcx"]->activateWindow();

    Form_xxcx * f = qobject_cast<Form_xxcx*>(forms["xxcx"]);
    connect(f, &Form_xxcx::destroyW, [=]{
        delete f;
        forms["xxcx"] = NULL;
    }
    );
}

void MainWindow::action_jsdz_trigged()
{
    //结算对账

    if(forms["jsdz"] == NULL){  //首次加载
        forms["jsdz"] = new Form_jsdz();
    }
    forms["jsdz"]->showNormal();
    forms["jsdz"]->activateWindow();

    Form_jsdz * f = qobject_cast<Form_jsdz*>(forms["jsdz"]);
    connect(f, &Form_jsdz::destroyW, [=]{
        delete f;
        forms["jsdz"] = NULL;
    }
    );
}

void MainWindow::action_dzbl_trigged()
{
    //门急诊上传,icpc上传 等

    if(forms["dzbl"] == NULL){  //首次加载
        forms["dzbl"] = new Form_dzbl();
    }
    forms["dzbl"]->showNormal();
    forms["dzbl"]->activateWindow();

    Form_dzbl * f = qobject_cast<Form_dzbl*>(forms["dzbl"]);
    connect(f, &Form_dzbl::destroyW, [=]{
        delete f;
        forms["dzbl"] = NULL;
    }
    );

}

void MainWindow::action_ybhj_trigged()
{
    //医保环境设置

    if(forms["ybhj"] == NULL){  //首次加载
        forms["ybhj"] = new Form_ybhj();
    }
    forms["ybhj"]->showNormal();
    forms["ybhj"]->activateWindow();

    Form_ybhj * f = qobject_cast<Form_ybhj*>(forms["ybhj"]);
    connect(f, &Form_ybhj::destroyW, [=]{
        delete f;
        forms["ybhj"] = NULL;
    }
    );

}

void MainWindow::action_InOut_trigged()
{
    //调剂室临时入出记账

    if(forms["iteminout"] == NULL){  //首次加载
        forms["iteminout"] = new Form_input();
    }
    forms["iteminout"]->showNormal();
    forms["iteminout"]->activateWindow();

    Form_input * f = qobject_cast<Form_input*>(forms["iteminout"]);
    connect(f, &Form_input::destroyW, [=]{
        delete f;
        forms["iteminout"] = NULL;
    }
    );

}


void MainWindow::action_qlsjsc_trigged()
{
    //进肖存数据上传

    if(forms["qlsjsc"] == NULL){  //首次加载
        forms["qlsjsc"] = new Form_qlsjsc();
    }
    forms["qlsjsc"]->showNormal();
    forms["qlsjsc"]->activateWindow();

    Form_qlsjsc * f = qobject_cast<Form_qlsjsc*>(forms["qlsjsc"]);
    connect(f, &Form_qlsjsc::destroyW, [=]{
        delete f;
        forms["qlsjsc"] = NULL;
    }
    );

}

void MainWindow::action_yk_rk_trigged()
{
    //药库，入库出库基础信息维护等

    if(forms["yk_rk"] == NULL){  //首次加载
        forms["yk_rk"] = new Form_yk_rk();
    }
    forms["yk_rk"]->showNormal();
    forms["yk_rk"]->activateWindow();

    Form_yk_rk * f = qobject_cast<Form_yk_rk*>(forms["yk_rk"]);
    connect(f, &Form_yk_rk::destroyW, [=]{
        delete f;
        forms["yk_rk"] = NULL;
    }
    );

}

void MainWindow::action_ys_bzgl_trigged()
{
    //医生门诊接诊处置

    if(abs(pub::check_system_time()) > 300)
    {
        QMessageBox::warning(NULL, "注意", "本机时间与服务器时间相差过大，请调整时间之后再运行！");
        return;
    }

    if(forms["ys_bzgl"] == NULL){  //首次加载
        forms["ys_bzgl"] = new Form_ys_bzgl();
    }
    forms["ys_bzgl"]->showNormal();
    forms["ys_bzgl"]->activateWindow();

    Form_ys_bzgl * f = qobject_cast<Form_ys_bzgl*>(forms["ys_bzgl"]);

    connect( f, &Form_ys_bzgl::trig_senior, this, &MainWindow::action_senior_reci_ck_trigged);

    connect(f, &Form_ys_bzgl::destroyW, [=]{
        delete f;
        forms["ys_bzgl"] = NULL;
    }
    );

}

void MainWindow::update_local_datetime(QString mode)
{
    QDateTime dttm;
    if(mode == "server")
    {
        qrm.exec("select now() from dual");
        qrm.next();

        dttm = qrm.value(0).toDateTime();
        qDebug()<<"使用数据库服务器时间 ： "<<dttm;
    }
    else if(mode == "insu")
    {


        while(true)
        {
            if(!initFinished)
            {
                QMessageBox::information(NULL,"note"," 动态库初始化尚未完成！");
            }
            else
            {
                break;
            }
        }
        QString inp = pub::getYbStrJ("5270","");   //获取医保系统时间
        if(inp.isEmpty()){

            QMessageBox::information(NULL,"note"," 5270 申请交易流水号失败！");
            return ; //未能成功申请交易流水号
        }
        currentInfno = "5270";

        QJsonObject in;

        in.insert("infno", "5270");
        in.insert( "msgid", inp);
        in.insert("mdtrtarea_admvs", pub::hos_insuplc);
        in.insert("insuplc_admdvs","");
        in.insert("recer_sys_code", "OwnSoft");
        in.insert("dev_no","");
        in.insert("dev_safe_info","");
        in.insert("cainfo", pub::hos_secretcode);
        in.insert("signtype","");
        in.insert("infver", "V1.0");
        in.insert("opter_type", "1");
        in.insert("opter", pub::usr_code);
        in.insert("opter_name", pub::usr_name);
        in.insert("inf_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
        in.insert("fixmedins_code", pub::hos_ybbh);
        in.insert("fixmedins_name", pub::hos_name);
        in.insert("sign_no", "");

        QJsonDocument indoc ;
        indoc.setObject(in);

        qDebug()<<"5270 indoc "<<indoc;

        //保存入参日志
        QString sq = "update com_business set v_in = '"
                + indoc.toJson(QJsonDocument::Compact)
                + "' where jyls = '" + inp + "'";

        if(!qrm.exec(sq)){
            QMessageBox::information(this,"错误","保存入参日志失败！");
            qDebug()<<sq;
        }

        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
        QNetworkAccessManager manager;
        QNetworkReply* rep = manager.post(request,indoc.toJson());

        QEventLoop eventLoop;
        QObject::connect(rep, SIGNAL(finished()), &eventLoop, SLOT(quit()));
        eventLoop.exec(); // 进入等待返回，但ui事件循环依然进行。

        QVariant statusCode = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute);

        if(!statusCode.isValid()){
            QMessageBox::warning(NULL,"注意","http 请求状态错误: " + statusCode.toString());
            return ;
        }

        QNetworkReply::NetworkError err = rep->error();

        if(err != QNetworkReply::NoError){
            QMessageBox::warning(NULL,"注意",rep->errorString());
            return ;
        }

        QByteArray bt = rpl->readAll();
        QString t = QString::fromLocal8Bit(bt);

        bt = rep->readAll();
        t = QString::fromLocal8Bit(bt);
        QJsonParseError json_error;
        QJsonDocument jsdc = QJsonDocument::fromJson(t.toUtf8(), &json_error);

        jsdc = QJsonDocument::fromJson(t.toUtf8(), &json_error);
        if(json_error.error != 0 ){
            QMessageBox::warning(NULL,"注意","返回信息解析错误 " + json_error.errorString());
            return ;
        }
        qDebug()<< "5270 outDoc "<<jsdc;
        QJsonObject jsob = jsdc.object();
        jsob = jsdc.object();

        sq = "update com_business set  tmstmp = now(), v_out = '"
                + jsdc.toJson(QJsonDocument::Compact)
                + "' , infcode = "
                + QString::number(jsob.value("infcode").toInt())
                + " where jyls = '" + inp + "'";

        if(!qrm.exec(sq)){
            QMessageBox::information(this,"错误","保存出参日志失败！");
            qDebug()<<sq;
        }


        if(jsob.value("infcode").toInt() != 0){
            QString t = jsob.value("err_msg").toString();
            QMessageBox::warning(NULL,"注意","5270 交易失败：" + t );

            return ;
        }
        QJsonObject ret = jsob.value("output").toObject().value("result").toObject();
        QString dtstr = ret.value("cent_time").toVariant().toString();
        dttm = QDateTime::fromString(dtstr, "yyyyMMddHHmmss");
        qDebug()<<"使用医保网络时间 ： "<<dttm;
    }
    else
    {
        return;
    }

    SYSTEMTIME st;
    GetLocalTime(&st); // Win32 API 获取系统当前时间，并存入结构体st中

    st.wYear = dttm.date().year();
    st.wMonth = dttm.date().month();
    st.wDay = dttm.date().day();
    st.wHour = dttm.time().hour();
    st.wMinute = dttm.time().minute();
    st.wSecond = dttm.time().second();
    //st.wMilliseconds = dttm.time().msec();
    SetLocalTime(&st);    //Win32 API 设置系统时间

    return;
}

void MainWindow::ybSign()
{
    QString inp;
    QString msgid;  //发送方报文ID ,定点医药机构编号(12)+时间(14)+顺序号(4)  时间格式：yyyyMMddHHmmss

    inp = pub::getYbStrJ("9001","");   //签到
    if(inp.isEmpty()){
        qDebug()<<"ybSign inp is null";
        QMessageBox::information(NULL,"note","申请交易流水号失败！");
        return ; //未能成功申请交易流水号
    }
    currentMsgid = inp;
    currentInfno = "9001";
    //msgid = pub::hos_ybbh + inp;
    msgid = inp;

    QJsonObject in;
    in.insert("infno", "9001");
    in.insert( "msgid", msgid);
    in.insert("mdtrtarea_admvs", pub::hos_insuplc);
    in.insert("insuplc_admdvs","");
    in.insert("recer_sys_code", "OwnSoft");
    in.insert("dev_no","");
    in.insert("dev_safe_info","");
    in.insert("cainfo", pub::hos_secretcode);
    in.insert("signtype","");
    in.insert("infver", "V1.0");
    in.insert("opter_type", "1");
    in.insert("opter", pub::usr_code);
    in.insert("opter_name", pub::usr_name);
    in.insert("inf_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
    in.insert("fixmedins_code", pub::hos_ybbh);
    in.insert("fixmedins_name", pub::hos_name);
    in.insert("sign_no", "");

    QJsonObject inpu,inpud;
    inpu.insert("opter_no", pub::usr_code); //操作员编号
    inpu.insert("mac", pub::localMac);//签到MAC地址
    inpu.insert("ip",pub::localIP);//签到IP地址
    inpud.insert("signIn",inpu);
    in.insert("input", inpud);

    QJsonDocument indoc ;
    indoc.setObject(in);
qDebug()<<"9001 indoc "<<indoc;
//保存入参日志
qrm.exec("update com_business set v_in = '"
         + indoc.toJson(QJsonDocument::Compact)
         + "' where jyls = '" + currentMsgid + "'");
    rpl = naManager->post(request, indoc.toJson());

}

void MainWindow::postRequestFinished(QNetworkReply *)
{
    httpFinished = true;
    tm->stop();
    QVariant statusCode = rpl->attribute(QNetworkRequest::HttpStatusCodeAttribute);

    if(!statusCode.isValid()){
        QMessageBox::warning(NULL,"注意","9001 http 请求状态错误: " + statusCode.toString());
        ybSigned = false;

        return;
    }

    QNetworkReply::NetworkError err = rpl->error();

    if(err != QNetworkReply::NoError){
        QMessageBox::warning(NULL,"注意","9001:"+rpl->errorString());
        ybSigned = false;

        return;
    }else{
        QByteArray bt = rpl->readAll();
        QString t = QString::fromLocal8Bit(bt);
        qDebug()<<"outDoc"<<t;
        QJsonParseError json_error;
        QJsonDocument jsdc = QJsonDocument::fromJson(t.toUtf8(), &json_error);
        if(json_error.error != 0 ){
            QMessageBox::warning(NULL,"注意","9001返回信息解析错误 " + json_error.errorString());
            ybSigned = false;

            return;
        }
        QJsonObject jsob = jsdc.object();

        qrm.exec("update com_business set  tmstmp = now(), v_out = '"
                 + jsdc.toJson(QJsonDocument::Compact)
                 + "'  , infcode = "
                 + QString::number(jsob.value("infcode").toInt())
                  +  " where jyls = '" + currentMsgid + "'");

        qDebug()<<"9001 return is "<<jsdc;
        if(jsob.value("infcode").toInt() != 0){
            QString t = jsob.value("err_msg").toString();
            QMessageBox::warning(NULL,"注意","交易失败:" + t );
        }else if(currentInfno == "9001"){
            QJsonObject jsobo = jsob.value("output").toObject().value("signinoutb").toObject();

            pub::sign_no = jsobo.value("sign_no").toString();
            pub::sign_time = jsobo.value("sign_time").toString();
            ybSigned = true;
            qDebug()<<pub::sign_no;
            qDebug()<<pub::sign_time;
            qDebug()<<"ybSigned";
        }else if(currentInfno == "9002"){
            QJsonObject jsobo = jsob.value("output").toObject().value("signoutoutb").toObject();
            pub::sign_time = jsobo.value("sign_time").toString();
            qDebug()<<pub::sign_time;
            qDebug()<<"ybSign";
            return; // 注销操作，后续操作无用，直接返回。
        }
        pub::useInsurance = true;  //医保可用

    }

    //pub::useInsurance = true;  //医保可用
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    //|窗口关闭之前需要的操作~
    QMessageBox:: StandardButton result= QMessageBox::warning(NULL, "注意", "确定要退出管理系统？",QMessageBox::Yes|QMessageBox::No);
    if(result == QMessageBox::No){
        event->ignore();
        return;
    }

    if(!pub::sign_no.isEmpty()){

        QString inp;

        inp = pub::getYbStrJ("9002","");   //签到
        if(inp.isEmpty()){
            QMessageBox::information(NULL,"note","申请交易流水号失败！");
            //直接退出
        }else{
            currentInfno = "9002";
            currentMsgid = inp;

            QJsonObject in;
            in.insert("infno", "9002");
            in.insert( "msgid", currentMsgid);
            in.insert("mdtrtarea_admvs", pub::hos_insuplc);
            in.insert("insuplc_admdvs","");
            in.insert("recer_sys_code", "OwnSoft");
            in.insert("dev_no","");
            in.insert("dev_safe_info","");
            in.insert("cainfo", pub::hos_secretcode);
            in.insert("signtype","");
            in.insert("infver", "V1.0");
            in.insert("opter_type", "1");
            in.insert("opter", pub::usr_code);
            in.insert("opter_name", pub::usr_name);
            in.insert("inf_time", QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
            in.insert("fixmedins_code", pub::hos_ybbh);
            in.insert("fixmedins_name", pub::hos_name);
            in.insert("sign_no", pub::sign_no);

            QJsonObject inpu,inpud;
            inpu.insert("opter_no", pub::usr_code); //操作员编号
            inpu.insert("sign_no", pub::sign_no);//签到MAC地址

            inpud.insert("signOut",inpu);
            in.insert("input", inpud);

            QJsonDocument indoc ;
            indoc.setObject(in);
            qDebug()<<"indoc"<<indoc;
            rpl = naManager->post(request, indoc.toJson());

            httpFinished = false;
            QString t0 = this->windowTitle();
            QString t;
            while(true){
                QThread::msleep(330);
                t = this->windowTitle();

                if( t.isEmpty()){
                    t = t0;
                }else{
                    t = "";
                }
                this->setWindowTitle(t);
                qApp->processEvents();
                if(httpFinished){
                    break;
                }
            }
        }
    }

    qro.exec("update com_loginlog set logout_date = sysdate "
             " where log_index = '" + pub::LOGINSESSION + "'");

    //主窗口关闭之前，查询是否有未关闭的子窗口

    qDebug()<<"主窗口关闭之前，查询是否有未关闭的子窗口\n";
    close_windows();

    if(share.attach())
    {
        if(share.lock())
        {
            char * d = (char *)share.data();
            *d = '0';
            share.unlock();
        }
    }

    //停止服务
    qDebug()<<"停止 tcp_server 服务\n";
    tcp_server->close();
    //tcp_server->deleteLater();

}

void MainWindow::close_windows(QString mode)
{

    qDebug()<<"close all windows.";

    if( mode !="resignin" && com_re_signin != NULL )
    {
        delete com_re_signin;
    }

    QMap<QString, QWidget *>::iterator it;

    for(it = forms.begin(); it != forms.end(); it ++)
    {
        delete it.value();
        //it.value()->close();
        forms.insert(it.key(), NULL);

    }
}

void MainWindow::destroyWind( QString w)
{
    //需要关闭即销毁的窗口，可以在这里进行处理
//    qDebug()<<"close window title : " <<w;
//    qDebug()<<"window is : " << forms[w];

//    if(forms[w] != NULL)
//    {
//        delete forms["w"];
//        forms.insert(w, NULL);
//    }

}

void MainWindow::re_signin()
{
    //变更登录身份

    qDebug()<<"re_signin.";
    //关闭已经打开的窗口
    close_windows("resignin");

    //提取用户已授权菜单项
    QString sq = "select r.menu_id from com_roles r,com_privileges p where p.type = 'role' "
                 " and r.role_name = p.role_dept and p.code = '" + pub::usr_code + "' ";
    qrm.exec(sq);
    QString ids;

    while(qrm.next())
    {
        ids += qrm.value(0).toString() + "^" ;
    }

    //提取需要显示到工具栏的菜单项
    sq = "select name from com_privileges where type = 'tool_bar' ";
    qrm.exec(sq);
    QString tools;

    while(qrm.next())
    {
        tools += qrm.value(0).toString() + "^" ;
    }


    ui->tbMain->clear();

    //移除未被授权菜单项,添加授权项目到工具栏
    foreach(QAction *a, ui->menubar->actions())
    {
        if( ids.indexOf(a->menu()->objectName() ) < 0 )
        {
            //ui->menubar->removeAction(a);
            a->setVisible(false);
        }
        else
        {
            a->setVisible(true);

            ui->tbMain->addSeparator();
            foreach(QAction *b, a->menu()->actions())
            {
                QString item_name = b->objectName();
                if( ids.indexOf(item_name) < 0)
                {
                    //a->menu()->removeAction(b);
                    b->setVisible(false);
                }
                else
                {
                    b->setVisible(true);
                    if( tools.indexOf(item_name) > -1)
                    {
                        ui->tbMain->addAction(b);
                    }
                }
            }
        }
    }

    QString title = "门诊简易系统 - Built at " + pub::local_version + " - " ;
    title += pub::hos_name;
    //title += " - Version  " +  + "  D.P. Sun";
    title += " - " + pub::usr_name;
    title += " - " + pub::dp_name;

    if(pub::DEBUG)
    {
        title += " （当前登录为测试模式）";
    }

    this->setWindowTitle( title );

    //注销当前登录
    qro.exec("update com_loginlog set logout_date = sysdate "
             " where log_index = '" + pub::LOGINSESSION + "'");

    //按新身份登录
    qro.exec("select sid,serial# from v$session "
              " where audsid = (select userenv('SESSIONID') From DUAL)");
    qro.next();

    QString sid = qro.value(0).toString();
    QString serial = qro.value(1).toString();

    qro.exec("SELECT SEQ_COM_LOGINSESSION.NEXTVAL FROM DUAL");
    qro.next();
    pub::LOGINSESSION = qro.value(0).toString();

    QString tmp_sq;

    tmp_sq = "insert into com_loginlog ("
             " log_index, empl_code, si_code, empl_name,login_date,"
             " dept_code, dept_name, sid, serial,"
             " log_machine, group_name, log_address) "
             " values (";
    tmp_sq += "'" + pub::LOGINSESSION + "',";
    tmp_sq += "'" + pub::usr_code + "',";
    tmp_sq += "'" + pub::dr_codg + "',";
    tmp_sq += "'" + pub::usr_name + "',";
    tmp_sq += "sysdate, ";
    tmp_sq += "'" + pub::dp_code + "',";
    tmp_sq += "'" + pub::dp_name + "',";
    tmp_sq += "'" + sid + "',";
    tmp_sq += "'" + serial + "',";
    tmp_sq += "'" + QHostInfo::localHostName() + "',";
    tmp_sq += "'" + pub::dp_name + "',";
    tmp_sq += "'" + pub::localIP + "'";
    tmp_sq += ")";
    qro.exec(tmp_sq);

    qDebug()<<"relogin : "<<tmp_sq;
}

void MainWindow::send_file_chunk()//qint64
{
    tm_receive->start(3000);
    qDebug()<<"bytesWritten >= bytesToSend:"
           <<QString::number(bytesWritten)<<" , "<<QString::number(bytesToSend);
    if (bytesWritten >= bytesToSend)
    {
        file.close();
        qDebug()<<"File sent successfully";
        tcp_socket->disconnectFromHost();
        tcp_socket->deleteLater();
        tcp_socket = nullptr;

        disconnect(tcp_socket, &QTcpSocket::bytesWritten,
                this, &MainWindow::send_file_chunk);
        //tm_log->start(TIMER_LOG);

        qDebug()<<"tcp socket disconnect after send file contain. \n";

        return;
    }

    if (!file.atEnd())
    {
        QByteArray buffer = file.read(16384); // 16KB chunks
        qint64 bytes = tcp_socket->write(buffer);
        if (bytes != -1)
        {
            bytesWritten += bytes;
            //progressBar->setValue(static_cast<int>(bytesWritten / static_cast<double>(bytesToSend) * 100));
        }
    }
}

bool MainWindow::manipulate_query(QJsonObject ob)
{
    qDebug()<<"\nmanipulate_query(QJsonObject ob) start.\n";

    QString dest = ob.value("dest").toString();
    QString dir_mode = ob.value("dir_mode").toString();
    QString name = ob.value("name").toString();

    if(dest == "dir")
    {
        if(dir_mode == "log")
        {

            tm_receive->start(3000);

            qDebug()<<"更新日志信息\n";
            QString basePath = pub::base_path + "/logs";

            QDir d = QDir(basePath);

            QStringList log_file_list;

            int file_list_size = 0;
            //总字节数 = 4 字节（元素数量） + ∑(4 字节（长度头） + 字符数 × 2 字节（数据）)

            if(d.exists())
            {
                d.setNameFilters( QStringList("*.log") );
                QStringList files = d.entryList();  //read filenames

                QFile f;
                QString file_name_full;

                foreach(QString flnm, files)
                {
                    file_name_full = basePath + "/" + flnm;
                    f.setFileName(file_name_full);

                    QString flinfo = file_name_full + "^" + QString::number(f.size());
                    log_file_list << flinfo;
                    file_list_size += 4 + flinfo.size() * 2;

                    qDebug()<<"file info : "<<flinfo;
                }
                if(file_list_size > 0)
                {
                    file_list_size += 4;
                }
            }

            QByteArray buffer;// = .; // 16KB chunks

            QDataStream stream(&buffer, QIODevice::WriteOnly);

            qDebug()<<"int size : "<<QString::number(sizeof(int));
            qDebug()<<"stringlist size : "<<QString::number(file_list_size);

            file_list_size += sizeof (int);
            stream <<file_list_size<< log_file_list; // 序列化到字节数组

            qDebug()<<"buffer size : "<<buffer.size();
            //qDebug()<<"buffer will send : "<<buffer;

            qint64 bytes = tcp_socket->write(buffer);
            if (bytes == -1)
            {
                qDebug()<<"tcp socket 写入错误\n";
                return false;
            }

//            tcp_socket->disconnectFromHost();
//            tcp_socket->deleteLater();
//            tcp_socket = nullptr;

//            qDebug()<<"tcp socket disconnect after send filelist \n";

        }
        else if(dir_mode == "any")
        {

        }
        else
        {
            qDebug()<<"参数错误，dir_mode 无效\n";
            return false;
        }
    }
    else if(dest == "file")
    {
            fileName = ob.value("name").toString();

            file.setFileName(fileName);

            if (!file.open(QIODevice::ReadOnly))
            {
                QMessageBox::critical(this, "Error", "Cannot open file");
                qDebug()<<"\nCannot open file   \n ";
                return false;
            }

            fileSize = file.size();
            bytesToSend = fileSize;
            bytesWritten = 0;
            QByteArray buffer;
           // QDataStream in(buffer);

           buffer = file.read(16384); // 16KB chunks
            qint64 bytes = tcp_socket->write(buffer);
            if (bytes != -1)
            {
                bytesWritten += bytes;
                 qDebug()<<"file write start  , "<<QString::number(bytesWritten)<<"\n";
            }
            else
            {
                qDebug()<<"file write error. \n";
                return false;
            }

            connect(tcp_socket, &QTcpSocket::bytesWritten,
                    this, &MainWindow::send_file_chunk);

    }
    else
    {
        qDebug()<<"参数错误，dest 无效\n";
        return false;
    }

    qDebug()<<"manipulate_query(QJsonObject ob) end, normal.\n";
    return true;
}

void MainWindow::tcp_connect_timeout()
{

    qDebug()<<"connect time out \n";

    if (tcp_socket == nullptr)
    {
        qDebug()<<"connect time out && current_socket == nullptr\n";
    }
    else
    {
        qDebug()<<"current_socket != nullptr\n";

        if(!tcp_socket->isValid())
        {
            qDebug()<<"connect time out && current_socket is invalid\n";
        }
        else
        {
            switch (tcp_socket->state()) {
            case QAbstractSocket::UnconnectedState:
                qDebug() << "Unconnected";
                break;
            case QAbstractSocket::HostLookupState:
                qDebug() << "Host lookup in progress";
                break;
            case QAbstractSocket::ConnectingState:
                qDebug() << "Connecting";
                break;
            case QAbstractSocket::ConnectedState:
                qDebug() << "Connected";
                tcp_socket->disconnectFromHost();
                break;
            case QAbstractSocket::BoundState:
                qDebug() << "Bound";
                break;
            case QAbstractSocket::ListeningState:
                qDebug() << "Listening";
                break;
            case QAbstractSocket::ClosingState:
                qDebug() << "Closing";
                break;
            default:
                qDebug() << "Unknown state";
                break;
            }

            tcp_socket->deleteLater();
            tcp_socket = nullptr;
        }
    }
}


void MainWindow::accept_connection()
{

    qDebug()<<"accept-connection ,\n";
    tm_receive->start(3000);
//    QTcpSocket *clientSocket = tcp_server->nextPendingConnection();
//    tcp_socket = clientSocket;

    tcp_socket = tcp_server->nextPendingConnection();
    //tcp_socket = clientSocket;

    QString strIP = tcp_socket->peerAddress().toString();
    quint16 nPort = tcp_socket->peerPort();

    qDebug()<<"remote info : "<<strIP <<" , " << QString::number(nPort)<<"\n";

    connect(tcp_socket, &QTcpSocket::readyRead,
            this, &MainWindow::read_client_data);

    //connect(tcp_socket, &QTcpSocket::disconnected,tcp_socket, &QTcpSocket::deleteLater);

}

void MainWindow::read_client_data()
{
    qDebug()<<"\nread_client_data()\n";

    //获取对方的IP和端口, 从通信套接字中取出内容

    QByteArray array;
    QDataStream in(tcp_socket);
    //in.setVersion(QDataStream::Qt_5_12);

    qDebug()<<"current_socket->bytesAvailable() : "
           <<QString::number(tcp_socket->bytesAvailable())<<"\n";

    // 统一使用 QDataStream 读取
    in >> array;

    qDebug() <<"套接字中取出内容:" << QString(array)<<"\n";

    QString ss= QVariant(array).toString();
    int pos = ss.indexOf("{");

    if(pos<0){
        qDebug() << "not is a valid json.";
        qDebug() << ss;
        return;
    }

    ss = ss.mid(pos);

    QJsonParseError json_error;

    QJsonDocument jsdc = QJsonDocument::fromJson(ss.toUtf8(), &json_error);


    if(json_error.error != 0 ){
        qDebug()<<"接收信息解析错误 " << json_error.errorString();
        return;
    }

    QJsonObject ob = jsdc.object();
    qDebug()<<"received jsonObject : "<<ob;

    manipulate_query(ob);

}
